//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package impl

import (
	"context"
	"fmt"
	"net"
	"time"

	"atomgit.com/openlinksaas-org/netutil/gen_code"
)

type ScanApiImpl struct{}

func (s *ScanApiImpl) ScanTcpportPost(ctx context.Context, req gen_code.ScanTcpportPostRequest) (gen_code.ImplResponse, error) {
	defer func() {
		recover()
	}()
	if req.Token != token {
		return gen_code.ImplResponse{
			Code: 500,
			Body: gen_code.ErrInfo{
				ErrMsg: "wrong token",
			},
		}, nil
	}
	reqChan := make(chan int32, 10)
	resChan := make(chan int32, 10)

	defer close(reqChan)
	defer close(resChan)

	for i := 0; i < 200; i++ {
		go func() {
			defer func() {
				recover()
			}()
			for {
				port := <-reqChan
				conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", req.Addr, port), 1*time.Second)
				if err == nil {
					conn.Close()
					resChan <- port
				} else {
					resChan <- 0
				}
			}
		}()
	}
	go func() {
		for port := req.From; port <= req.To; port += 1 {
			reqChan <- port
		}
	}()

	recvCount := 0
	resList := []int32{}
	for {
		port := <-resChan
		if port > 0 {
			resList = append(resList, port)
		}
		recvCount += 1
		if recvCount >= int(req.To-req.From+1) {
			break
		}
	}
	return gen_code.ImplResponse{
		Code: 200,
		Body: resList,
	}, nil
}
